package com.meizi.codegenerate.generate.clien.domain.repository;

import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.meizi.codegenerate.constant.JavaClassNameConstant;
import com.meizi.codegenerate.constant.MethodNameConstant;
import com.meizi.codegenerate.constant.TableNameConstant;
import com.meizi.codegenerate.entity.ProjectPositionEntity;
import com.meizi.codegenerate.entity.TablesEntity;
import com.meizi.codegenerate.generate.server.domain.repository.impl.RepositoryGenerate;
import com.meizi.codegenerate.packagegenerate.PackageGenerate;
import com.meizi.codegenerate.tool.page.PageData;
import com.meizi.codegenerate.utils.AttributeConvertUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * @author pc
 * @date 2024/1/19 - 11:30 - 星期五
 * @project lambda
 * @package com.meizi.codegenerate.generate.clien.domain.repository
 * @by GGbomd猪猪侠
 */
@Slf4j
public class IRepositoryGenerate {


    /**
     * 创建 IRepository interface
     * @throws IOException
     */
    public static void createIRepositoryGenerate(String tableName, TablesEntity tablesComment, ProjectPositionEntity projectPosition, String paramQueryBody) throws IOException {
        // 在相应的路径下创建对应的文件
        String serviceUrl = PackageGenerate.obtainRepositoryUrl(projectPosition);

        //获取Repository java类名
        String className = "I" + AttributeConvertUtils.tableNameToJava
                (tableName, TableNameConstant.TABLE_PREFIX, true)
                + JavaClassNameConstant.REPOSITORY;
        // 获取完成的文件路径创建文件
        String fullPath = serviceUrl + className + TableNameConstant.JAVA;
        log.info("创建 domain 下IRepository路径 fullPath = {}", fullPath);

        CompilationUnit compilationUnit = new CompilationUnit();
        // 添加package
        compilationUnit.setPackageDeclaration(PackageGenerate.repositoryPackage(projectPosition));

        // 添加接口文件
        ClassOrInterfaceDeclaration declaration = compilationUnit.addInterface(className).setPublic(true);
        //添加类级别注释
        declaration.setJavadocComment(tablesComment.getTableComment() + " 仓储层接口");

        // 获取返回传参
        String returnParam = AttributeConvertUtils.tableNameToJava
                (tableName, TableNameConstant.TABLE_PREFIX, true);
        //添加抽象方法 getList
        MethodDeclaration getListMethod = methodGetList(MethodNameConstant.SERVICE_GET_LIST, returnParam, paramQueryBody);
        declaration.addMember(getListMethod);

        //添加抽象方法 getPageList
        MethodDeclaration getPageListMethod = methodGetPageList(MethodNameConstant.SERVICE_GET_PAGE_LIST, returnParam, paramQueryBody);
        declaration.addMember(getPageListMethod);

        //添加抽象方法 getCount
        MethodDeclaration getCountMethod = methodGetCount(MethodNameConstant.SERVICE_GET_COUNT, paramQueryBody);
        declaration.addMember(getCountMethod);

        //添加抽象方法 exists
        MethodDeclaration existsMethod = methodGetexists(MethodNameConstant.SERVICE_EXISTS, paramQueryBody);
        declaration.addMember(existsMethod);

        //添加抽象方法 getDetailById
        MethodDeclaration getDetailByIdMethod = methodGetDetailById(MethodNameConstant.SERVICE_GET_DETAIL_BYID, returnParam);
        declaration.addMember(getDetailByIdMethod);

        //添加抽象方法 getIdList
        /*MethodDeclaration getIdListMethod = methodGetIdListMethod(MethodNameConstant.SERVICE_GET_ID_LIST, paramQueryBody);
        declaration.addMember(getIdListMethod);*/

        MethodDeclaration createMethod = methodCreate(MethodNameConstant.SERVICE_CREATE, returnParam);
        declaration.addMember(createMethod);

        //添加抽象方法 createBatch
        MethodDeclaration createBatchMethodSize = methodCreateBatchSize(MethodNameConstant.SERVICE_CREATE_BATH, returnParam);
        declaration.addMember(createBatchMethodSize);

        MethodDeclaration createBatchMethod = methodCreateBatch(MethodNameConstant.SERVICE_CREATE_BATH, returnParam);
        declaration.addMember(createBatchMethod);

        //添加抽象方法 updateModel
        MethodDeclaration updateModelMethod = methodUpdateModel(MethodNameConstant.SERVICE_UPDATE_MODEL, returnParam);
        declaration.addMember(updateModelMethod);


        MethodDeclaration updateModelMethodSize = methodUpdateModelSize(MethodNameConstant.SERVICE_UPDATE_MODEL_BATH, returnParam, paramQueryBody);
        declaration.addMember(updateModelMethodSize);

        //添加抽象方法 saveModel
        MethodDeclaration saveModelMethod = methodSaveModel(MethodNameConstant.SERVICE_SAVE_MODEL, returnParam);
        declaration.addMember(saveModelMethod);

        //添加抽象方法 delete
        MethodDeclaration deleteMethod = methodDelete(MethodNameConstant.SERVICE_DELETE, paramQueryBody);
        declaration.addMember(deleteMethod);

        //添加抽象方法 deleteById
        MethodDeclaration deleteByIdMethod = methodDeleteById(MethodNameConstant.SERVICE_DELETE_BYID);
        declaration.addMember(deleteByIdMethod);

        log.info("生成IRepository 接口 compilationUnit = {}", compilationUnit.toString());

        /**
         * 把字符串写入文件
         * 参数1：需要写入的文件，如果文件不存在，将自动创建。  参数2：需要写入的内容
         * 参数3：编码格式     参数4：是否为追加模式（ ture: 追加模式，把字符串追加到原内容后面）
         */
        FileUtils.writeStringToFile(new File(fullPath), compilationUnit.toString(), "UTF-8", false);

        // 生成仓储曾实现
        RepositoryGenerate.createRepositoryGenerate(tableName, tablesComment, projectPosition, paramQueryBody, className);
    }

    private static MethodDeclaration methodDeleteById(String name) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, Long.class.getSimpleName()), "id"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodDelete(String name, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, paramQueryBody), "condition"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodSaveModel(String name, String returnParam) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, returnParam), "model"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodUpdateModel(String name, String returnParam) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, returnParam), "model"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodUpdateModelSize(String name, String returnParam, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        ClassOrInterfaceType model = new ClassOrInterfaceType(returnParam);
        ClassOrInterfaceType query = new ClassOrInterfaceType(paramQueryBody);

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter().setType(model).setName("model"));
        method.addParameter(new Parameter().setType(query).setName("condition"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodCreateBatch(String name, String returnParam) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        ClassOrInterfaceType listType = new ClassOrInterfaceType(List.class.getSimpleName());
        ClassOrInterfaceType model = new ClassOrInterfaceType(returnParam);
        listType.setTypeArguments(model);

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter().setType(listType).setName("models"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodCreateBatchSize(String name, String returnParam) {
        // 添加返回值类型
        ClassOrInterfaceType inte = new ClassOrInterfaceType(Integer.class.getSimpleName());

        ClassOrInterfaceType listType = new ClassOrInterfaceType(List.class.getSimpleName());
        ClassOrInterfaceType model = new ClassOrInterfaceType(returnParam);
        listType.setTypeArguments(model);

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(inte);
        method.setName(name);
        method.addParameter(new Parameter().setType(listType).setName("models"));
        method.addParameter(new Parameter().setType(Integer.class.getSimpleName()).setName("batchSize"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodCreate(String name, String returnParam) {
        // 添加返回值类型
        ClassOrInterfaceType listType = new ClassOrInterfaceType(Integer.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, returnParam), "model"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodGetIdListMethod(String name, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType mapType = new ClassOrInterfaceType(Long.class.getSimpleName());
        ClassOrInterfaceType listType = new ClassOrInterfaceType(List.class.getSimpleName());
        listType.setTypeArguments(mapType);

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, paramQueryBody), "queryBody"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodGetDetailById(String name, String returnParam) {
        // 添加返回值类型
        ClassOrInterfaceType listType = new ClassOrInterfaceType(returnParam);

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, Long.class.getSimpleName()), "id"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodGetexists(String name, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType listType = new ClassOrInterfaceType(Boolean.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, paramQueryBody), "queryBody"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodGetCount(String name, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType listType = new ClassOrInterfaceType(Integer.class.getSimpleName());

        // 生成方法
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, paramQueryBody), "queryBody"));

        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodGetPageList(String name, String returnParam, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType mapType = new ClassOrInterfaceType(returnParam);
        ClassOrInterfaceType listType = new ClassOrInterfaceType(PageData.class.getSimpleName());
        listType.setTypeArguments(mapType);

        // 生成方法 GetPageList
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, paramQueryBody), "queryBody"));
        
        // 去除方法体
        method.setBody(null);

        return method;
    }

    private static MethodDeclaration methodGetList(String name, String returnParam, String paramQueryBody) {
        // 添加返回值类型
        ClassOrInterfaceType mapType = new ClassOrInterfaceType(returnParam);
        ClassOrInterfaceType listType = new ClassOrInterfaceType(List.class.getSimpleName());
        listType.setTypeArguments(mapType);

        // 生成方法 getList
        MethodDeclaration method = new MethodDeclaration();
        method.setType(listType);
        method.setName(name);
        method.addParameter(new Parameter(new ClassOrInterfaceType(null, paramQueryBody), "queryBody"));

        // 去除方法体
        method.setBody(null);

        return method;
    }


}
